package com.lastproject.ejb.dao;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import annotations.PermissionAnnotation;

import com.lastproject.dto.CategoryDTO;
import com.lastproject.dto.SubcategoryDTO;
import com.lastproject.dto.SurveyDTO;
import com.lastproject.dto.TopicDTO;
import com.lastproject.dto.UserDTO;
import com.lastproject.ejb.entities.Category;
import com.lastproject.ejb.entities.EmailGroup;
import com.lastproject.ejb.entities.Survey;
import com.lastproject.ejb.entities.Topic;
import com.lastproject.ejb.entities.User;
import com.lastproject.ejb.interceptors.PermissionInterceptor;
import com.lastproject.ejb.util.CategoryConversion;
import com.lastproject.ejb.util.EmailGroupConversion;
import com.lastproject.ejb.util.SubcategoryConversion;
import com.lastproject.ejb.util.SurveyConversion;
import com.lastproject.ejb.util.TopicConversion;
import com.lastproject.ejb.util.UserConversion;

/**
 * Session Bean implementation class SurveyDAO
 * 
 * @Author : Zier Erik
 */
@Stateless
public class SurveyDAO implements SurveyDAORemote {

	@PersistenceContext
	private EntityManager em;

	@EJB
	SurveyConversion sconv;

	@EJB
	TopicConversion tconv;

	@EJB
	CategoryConversion cconv;

	@EJB
	SubcategoryConversion subconv;

	@EJB
	UserConversion uconv;
	EmailGroupConversion gconv;

	public SurveyDAO() {
	}

	@Interceptors(PermissionInterceptor.class)
	@PermissionAnnotation(canCreateQuiz = 1)
	@Override
	public boolean create(boolean hasPermission, SurveyDTO entity) {
		if (hasPermission) {
			Survey survey = sconv.fromDTO(entity);

			Topic topic = em.find(Topic.class, entity.getIdTopic());
			survey.setTopic(topic);

			User user = em.find(User.class, entity.getIdUser());
			survey.setUser(user);

			em.persist(survey);
			em.flush();
			em.refresh(survey);

			user.addInSurveyList(survey);
			return true;
		}
		else{
			return false;
		}

	}

	@Interceptors(PermissionInterceptor.class)
	@PermissionAnnotation(canCreateQuiz = 1)
	@Override
	public boolean edit(boolean hasPermission, SurveyDTO entity) {
		if (hasPermission) {
			Survey survey = em.find(Survey.class, entity.getId());
			survey.setTopic(em.find(Topic.class, entity.getIdTopic()));
			survey.setEmailGroup(em.find(EmailGroup.class, entity
					.getEmailGroup().getId()));
			em.merge(survey);
			return true;
		}
		else{
			return false;
		}
	}

	@Interceptors(PermissionInterceptor.class)
	@PermissionAnnotation(canCreateQuiz = 1)
	@Override
	public boolean remove(boolean hasPermission, SurveyDTO entity) {
		if (hasPermission){
		Survey survey = em.find(Survey.class, sconv.fromDTO(entity).getId());
		em.remove(survey);
		return true;
		}
		else{
			return false;
		}
	}

	@Override
	public SurveyDTO findById(Object id) {
		Survey survey = em.find(Survey.class, id);
		return sconv.fromEntity(survey);
	}

	@Override
	public List<SurveyDTO> findAll() {

		List<Survey> surveys = em.createNamedQuery("Survey.findAll",
				Survey.class).getResultList();

		List<SurveyDTO> surveydtolist = new ArrayList<SurveyDTO>();

		for (Survey survey : surveys) {

			SurveyDTO sDto = new SurveyDTO();
			sDto = sconv.fromEntity(survey);
			surveydtolist.add(sDto);
		}

		return surveydtolist;
	}

	// returns a list of surveys by idUser
	@Override
	public List<SurveyDTO> getSurveyListByUserId(int idUser) {
		List<Survey> surveys = em
				.createQuery(
						"SELECT s FROM Survey s WHERE s.user.id = :id ORDER BY s.endDate DESC",
						Survey.class).setParameter("id", idUser)
				.getResultList();

		List<SurveyDTO> surveydtolist = new ArrayList<SurveyDTO>();

		for (Survey survey : surveys) {

			SurveyDTO sDto = new SurveyDTO();
			sDto = sconv.fromEntity(survey);
			surveydtolist.add(sDto);
		}

		return surveydtolist;
	}

	// returns a survey by id
	@Override
	public SurveyDTO getSurveyById(int idSurvey) {
		Survey survey = em.find(Survey.class, idSurvey);

		if (survey != null) {
			SurveyDTO surveydto = new SurveyDTO();
			surveydto = sconv.fromEntity(survey);
			return surveydto;
		}
		return null;
	}

	// returns a topic by idSurvey
	@Override
	public TopicDTO getTopicBySurveyId(int idSurvey) {
		Topic topic = em
				.createQuery(
						"SELECT t FROM Topic t JOIN t.survey s WHERE s.id = :id",
						Topic.class).setParameter("id", idSurvey)
				.getSingleResult();

		TopicDTO topicdto = new TopicDTO();
		topicdto = tconv.fromEntity(topic);

		return topicdto;
	}

	@Override
	public CategoryDTO getCategoryBySurveyId(int idSurvey) {
		Category category = em
				.createQuery(
						"SELECT t FROM Topic t JOIN t.survey s WHERE s.id = :id",
						Category.class).setParameter("id", idSurvey)
				.getSingleResult();

		CategoryDTO categorydto = new CategoryDTO();
		categorydto = cconv.fromEntity(category);

		return categorydto;
	}

	@Override
	public SubcategoryDTO getSubcategoryBySurveyId(int idSurvey) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public UserDTO getUserBySurveyId(int idSurvey) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public SurveyDTO findByTitleTopicUser(String title, int idTopic, int idUser) {
		Survey s = new Survey();
		s = em.createNamedQuery("Survey.findByTitleTopicUser", Survey.class)
				.setParameter("title", title)
				.setParameter("topic", em.find(Topic.class, idTopic))
				.setParameter("user", em.find(User.class, idUser))
				.getResultList().get(0);
		return sconv.fromEntity(s);
	}

	@Override
	public SurveyDTO findLastByMe(int idUser) {
		List<Survey> sList = new ArrayList<Survey>();
		sList = em.createNamedQuery("Survey.findLastByMe", Survey.class)
				.setParameter("user", em.find(User.class, idUser))
				.getResultList();
		Survey s = new Survey();
		if (sList.size() != 0) {
			s = sList.get(sList.size() - 1);
			return sconv.fromEntity(s);
		}
		return null;
	}

	@Override
	public List<SurveyDTO> getSurveysByGroupId(int idGroup) {
		List<SurveyDTO> surveysDto = new ArrayList<SurveyDTO>();
		List<Survey> surveys = new ArrayList<Survey>();
		EmailGroup eg = em.find(EmailGroup.class, idGroup);
		surveys = em
				.createQuery("SELECT s FROM Survey s WHERE s.emailGroup = :id",
						Survey.class).setParameter("id", eg).getResultList();

		if (surveys.size() != 0) {
			for (Survey s : surveys) {
				SurveyDTO surveydto = new SurveyDTO();
				surveydto = sconv.fromEntity(s);
				surveysDto.add(surveydto);
			}
		}

		return surveysDto;
	}

}
